package club.framework.web.application.sys.menu.service.impl;


import club.framework.web.application.sys.menu.entity.Menu;
import club.framework.web.application.sys.menu.mapper.MenuMapper;
import club.framework.web.application.sys.menu.service.IMenuService;
import club.framework.web.application.sys.user.mapper.UserMapper;
import club.framework.web.base.entity.BasePageReqEntity;
import club.framework.web.base.entity.BasePageResultEntity;
import club.framework.web.base.util.ArabNumConventCNNumUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Stream;

/**
 * @date 2017/9/7.
 * @Email:sunmch@163.com
 * @author: 念梓
 * des:
 */
@Service
public class MenuServiceImpl implements IMenuService {

    private static final Logger log = LogManager.getLogger(MenuServiceImpl.class);

    private static final String FIRST_CODE="0001";

    private static final int ALONE_CODE_LENGTH=4;

    private static final int INIT_TREE_ID=0;

    @Resource
    private HttpServletRequest request;

    @Resource
    private MenuMapper menuMapper;

    @Resource
    private UserMapper userMapper;

    @Override
    public Menu getObject(Menu menu) {
        return null;
    }

    @Override
    public Menu getObject(int id) {
        return menuMapper.queryObjectById(id);
    }

    @Override
    public Menu getObject(long uid) {
        return null;
    }

    @Override
    public int save(Menu menu) {
        Date now = new Date();
        menu.setUpdateTime(now);
        menu.setCreateTime(now);
        Map<String,String> codeMap = loadCode(menu.getParentId(),menu.getStep());
        menu.setCode(codeMap.get("code"));
        menu.setParentCode(codeMap.get("parentCode"));
        return menuMapper.save(menu);
    }

    @Override
    public int delete(Menu menu) {
        return 0;
    }

    @Override
    public int delete(int id) {
        return 0;
    }

    @Override
    public int delete(long uid) {
        return 0;
    }

    @Override
    public int update(Menu menu) {
        menu.setUpdateTime(new Date());
        return menuMapper.update(menu);
    }

    @Override
    public BasePageResultEntity<Menu> queryPage(BasePageReqEntity<Menu> basePageReqEntity) {
        BasePageResultEntity<Menu> basePageResultEntity = new BasePageResultEntity<>();
        List<Menu> pageMenuList = menuMapper.queryPage(basePageReqEntity);
        int totalCount = menuMapper.queryTotalCount(basePageReqEntity.getObj());
        basePageResultEntity.setRows(pageMenuList);
        basePageResultEntity.setTotal(totalCount);
        return basePageResultEntity;
    }

    @Override
    public List<Menu> loadMenuByStep(int step) {
        int targetStep = step-1;
        return menuMapper.loadMenuByStep(targetStep);
    }

    @Override
    public List<Map<String,String>> loadMenuStep() {
        List<Integer> steps = menuMapper.loadMenuStep();
        steps.add(Collections.max(steps)+1);
        List<Map<String,String>> stepMenuList = new ArrayList<>();
        steps.forEach(e->{
            Map<String,String> map = new HashMap<String, String>();
            if(e == 0){
                map.put("value","");
                map.put("name","菜单层级");
            }else{
                map.put("value",String.valueOf(e));
                map.put("name","第"+ ArabNumConventCNNumUtils.getCNNum(e)+"级");
            }
            stepMenuList.add(map);
        });
        return stepMenuList;
    }

    /**
     * 获取新增的菜单所要求的code和parentcode
     * @return
     */
    private Map<String,String> loadCode(int parentId,int step){
        Map<String,String> codeMap = new HashMap<>();
        String parentCode = menuMapper.queryCodeById(parentId);
        codeMap.put("parentCode",parentCode);
        String maxCode = menuMapper.queryMaxCodeByParentId(parentId);
        if(StringUtils.isBlank(maxCode)){
            String code = parentCode+FIRST_CODE;
            codeMap.put("code",code);
        }else{
            String currentCode = maxCode.substring(step*ALONE_CODE_LENGTH);
            int targetCodeInt = Integer.parseInt(currentCode)+1;
            String targetCode= String.valueOf(targetCodeInt);
            int targetCodeLength = targetCode.length();
            if( targetCodeLength==1){
                targetCode="000"+targetCodeInt;
            }else if(targetCodeLength==2){
                targetCode="00"+targetCodeInt;
            }else if(targetCodeLength ==3){
                targetCode="0"+targetCodeInt;
            }
            codeMap.put("code",parentCode+targetCode);
        }
        return codeMap;
    }

    @Override
    public List<Menu> loadMenuByParentId(int parentId) {
        return menuMapper.loadMenuByParentId(parentId);
    }

    @Override
    public int deleteMenuByCode(String code) {
        return menuMapper.deleteMenuByCode(code);
    }

    @Override
    public Object loadMenuTreeByParentId(int parentId,int userId) {

        if(INIT_TREE_ID == parentId){
            Map<String,Object> stateMap = new HashMap<>();
            stateMap.put("opened",true);
            Map<String,Object> root = new HashMap<>();
            root.put("id",parentId);
            root.put("text","根节点");
            root.put("state",stateMap);
            root.put("children",loadTreeInfo(parentId,userId));
            return root;
        }else{
            return loadTreeInfo(parentId,userId);
        }
    }

    private Object loadTreeInfo(int parentId,int userId){
        List<Integer> menuIds = userMapper.getMenuIdByUserId(userId);
        List<Map<String,Object>> list = new ArrayList<>();
        List<Menu> menus = menuMapper.loadMenuByParentId(parentId);
        menus.forEach(e->{
            int childrenCount = menuMapper.queryTotalCountByParentId(e.getId());
            Map<String,Object> map = new HashMap<>();
            Map<String,Object> checkedMap = new HashMap<String, Object>();
            map.put("id",e.getId());
            map.put("text",e.getName());
            map.put("children",childrenCount==0?false:true);
            map.put("icon",childrenCount==0?"jstree-file":"");
            checkedMap.put("opened",true);
            if(menuIds.contains(e.getId())){
                checkedMap.put("selected",true);
                checkedMap.put("checked",true);
            }
            map.put("state",checkedMap);
            list.add(map);
        });
        return list;
    }
}
